package com.sx.export.Utils;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.zip.*;

@Component
public class SplitZipUtil {
    private static final int BUFFER_SIZE = 4096; // 缓冲区大小

    private static final int MAX_ZIP_SIZE = 1024 * 1024 * 10; // 300MB,可以改为自己想要的大小
    private static ZipOutputStream currentZipOutputStream = null;
    private static File currentZipFile = null;
    private static long totalBytesWritten = 0;
    private static int currentZipCount = 0;
    private static String basePath = ""; // 基本路径，用于在ZIP中保持相对路径

    private static String outZipName = "";//输出压缩包的名称

    public static void addFileToZip(File fileToAdd, String parentPath) throws IOException {
        long approximateFileSize = getApproximateFileSize(fileToAdd);//计算要压缩的文件（文件夹）大小
        if (currentZipOutputStream == null || (totalBytesWritten + approximateFileSize > MAX_ZIP_SIZE && totalBytesWritten != 0)) {
            closeCurrentZip();
            openNewZip();
        }

        if (fileToAdd.isDirectory()) {
            File[] files = fileToAdd.listFiles();
            if (files != null) {
                for (File file : files) {
                    addFileToZip(file, parentPath + fileToAdd.getName() + "/");
                }
            }
        } else {
            ZipEntry zipEntry = new ZipEntry(parentPath + fileToAdd.getName());
            currentZipOutputStream.putNextEntry(zipEntry);

            FileInputStream fis = new FileInputStream(fileToAdd);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = fis.read(buffer)) >= 0) {
                currentZipOutputStream.write(buffer, 0, length);
                totalBytesWritten += length; // 更新已写入的总字节数
            }
            fis.close();
            currentZipOutputStream.closeEntry();
        }
    }

    private static long getApproximateFileSize(File file) {
        if (file.isDirectory()) {
            long length = 0;
            File[] files = file.listFiles();
            if (files != null) {
                for (File childFile : files) {
                    length += getApproximateFileSize(childFile);
                }
            }
            return length;
        } else {
            return file.length();
        }
    }

    private static void openNewZip() throws IOException {
        totalBytesWritten = 0; // 重置已写入的字节数
        currentZipCount++;
        currentZipFile = new File(outZipName + "_" + currentZipCount + ".zip");
        currentZipOutputStream = new ZipOutputStream(new FileOutputStream(currentZipFile));
    }

    private static void closeCurrentZip() throws IOException {
        if (currentZipOutputStream != null) {
            currentZipOutputStream.close();
            currentZipOutputStream = null;
        }
    }

    public static void zipDirectory(File directoryToZip, String baseDirectoryPath) throws IOException {
        basePath = baseDirectoryPath;
        if (directoryToZip.isDirectory()) {
            addFileToZip(directoryToZip, "");
        } else {
            throw new IOException("The specified path is not a directory.");
        }
        closeCurrentZip(); // 确保关闭最后一个ZIP文件
    }

    /**
     * @param folder        要压缩的文件夹
     * @param targetZipName 生成压缩包的名称
     */
    public static void start(String folder, String targetZipName) throws Exception {
        if (StringUtils.isEmpty(folder) || StringUtils.isEmpty(targetZipName)) {
            throw new Exception("不能压缩。。。。。。");
        }
        outZipName = targetZipName;
        File dirToZip = new File(folder); // 替换为你要压缩的目录路径
        String baseDirPath = dirToZip.getName(); // 通常我们想要基于目录名来创建ZIP文件的根目录
        try {
            zipDirectory(dirToZip, baseDirPath + "/");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        SplitZipUtil splitZip = new SplitZipUtil();
        splitZip.start("D:\\test", "D:\\test1");
    }
}
